From 70a1233a282df3b3d89d2b40d7a5c5f101805862 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Tue, 19 Feb 2019 06:52:36 +0100 Subject: [PATCH] gsk: Add GskMatrixCategory We'll use that soon. --- gsk/gskrendernodeimpl.c | 46 ++++++++++++++++++++++++++++++++++---- gsk/gskrendernodeprivate.h | 43 +++++++++++++++++++++++++++++++++++ gtk/inspector/recorder.c | 9 ++++++++ 3 files changed, 94 insertions(+), 4 deletions(-) diff --git a/gsk/gskrendernodeimpl.c b/gsk/gskrendernodeimpl.c index 8b704aedda..34dd509d1f 100644 --- a/gsk/gskrendernodeimpl.c +++ b/gsk/gskrendernodeimpl.c @@ -2387,6 +2387,7 @@ struct _GskTransformNode GskRenderNode *child; graphene_matrix_t transform; + GskMatrixCategory category; }; static void @@ -2422,7 +2423,7 @@ gsk_transform_node_draw (GskRenderNode *node, } } -#define GSK_TRANSFORM_NODE_VARIANT_TYPE "(dddddddddddddddduv)" +#define GSK_TRANSFORM_NODE_VARIANT_TYPE "(idddddddddddddddduv)" static GVariant * gsk_transform_node_serialize (GskRenderNode *node) @@ -2433,6 +2434,7 @@ gsk_transform_node_serialize (GskRenderNode *node) graphene_matrix_to_float (&self->transform, mat); return g_variant_new (GSK_TRANSFORM_NODE_VARIANT_TYPE, + self->category, (double) mat[0], (double) mat[1], (double) mat[2], (double) mat[3], (double) mat[4], (double) mat[5], (double) mat[6], (double) mat[7], (double) mat[8], (double) mat[9], (double) mat[10], (double) mat[11], @@ -2448,6 +2450,7 @@ gsk_transform_node_deserialize (GVariant *variant, graphene_matrix_t transform; double mat[16]; guint32 child_type; + gint32 category; GVariant *child_variant; GskRenderNode *result, *child; @@ -2455,6 +2458,7 @@ gsk_transform_node_deserialize (GVariant *variant, return NULL; g_variant_get (variant, GSK_TRANSFORM_NODE_VARIANT_TYPE, + &category, &mat[0], &mat[1], &mat[2], &mat[3], &mat[4], &mat[5], &mat[6], &mat[7], &mat[8], &mat[9], &mat[10], &mat[11], @@ -2475,7 +2479,7 @@ gsk_transform_node_deserialize (GVariant *variant, mat[12], mat[13], mat[14], mat[15] }); - result = gsk_transform_node_new (child, &transform); + result = gsk_transform_node_new_with_category (child, &transform, category); gsk_render_node_unref (child); @@ -2508,15 +2512,39 @@ GskRenderNode * gsk_transform_node_new (GskRenderNode *child, const graphene_matrix_t *transform) { - GskTransformNode *self; - g_return_val_if_fail (GSK_IS_RENDER_NODE (child), NULL); g_return_val_if_fail (transform != NULL, NULL); + return gsk_transform_node_new_with_category (child, transform, GSK_MATRIX_CATEGORY_UNKNOWN); +} + +/* + * gsk_transform_node_new_with_category: + * @child: The node to transform + * @transform: The transform to apply + * @category: The category @transform belongs to + * + * Creates a #GskRenderNode that will transform the given @child + * with the given @transform. + * + * The given @category will be used by renderers for optimizations and must + * be correct. If you do not know the category of @transform, use + * %GSK_MATRIX_CATEGORY_UNKNOWN. + * + * Returns: A new #GskRenderNode + **/ +GskRenderNode * +gsk_transform_node_new_with_category (GskRenderNode *child, + const graphene_matrix_t *transform, + GskMatrixCategory category) +{ + GskTransformNode *self; + self = (GskTransformNode *) gsk_render_node_new (&GSK_TRANSFORM_NODE_CLASS, 0); self->child = gsk_render_node_ref (child); graphene_matrix_init_from_matrix (&self->transform, transform); + self->category = category; graphene_matrix_transform_bounds (&self->transform, &child->bounds, @@ -2552,6 +2580,16 @@ gsk_transform_node_peek_transform (GskRenderNode *node) return &self->transform; } +GskMatrixCategory +gsk_transform_node_get_category (GskRenderNode *node) +{ + GskTransformNode *self = (GskTransformNode *) node; + + g_return_val_if_fail (GSK_IS_RENDER_NODE_TYPE (node, GSK_TRANSFORM_NODE), GSK_MATRIX_CATEGORY_UNKNOWN); + + return self->category; +} + /*** GSK_OFFSET_NODE ***/ typedef struct _GskOffsetNode GskOffsetNode; diff --git a/gsk/gskrendernodeprivate.h b/gsk/gskrendernodeprivate.h index 145fec0955..1f0565cfab 100644 --- a/gsk/gskrendernodeprivate.h +++ b/gsk/gskrendernodeprivate.h @@ -6,6 +6,44 @@ G_BEGIN_DECLS +/* + * GskMatrixCategory: + * @GSK_MATRIX_CATEGORY_UNKNOWN: The category of the matrix has not been + * determined. + * @GSK_MATRIX_CATEGORY_ANY: Analyzing the matrix concluded that it does + * not fit in any other category. + * @GSK_MATRIX_CATEGORY_INVERTIBLE: The matrix is linear independant and + * should therefor be invertible. Note that this is not guaranteed + * to actually be true due to rounding errors when inverting. + * @GSK_MATRIX_CATEGORY_2D: The matrix is a 2D matrix. This is equivalent + * to graphene_matrix_is_2d() returning %TRUE. In particular, this + * means that Cairo can deal with the matrix. + * @GSK_MATRIX_CATEGORY_2D_AFFINE: The matrix is a combination of 2D scale + * and 2D translation operations. In particular, this means that any + * rectangle can be transformed exactly using this matrix. + * @GSK_MATRIX_CATEGORY_2D_TRANSLATE: The matrix is a 2D translation. + * @GSK_MATRIX_CATEGORY_IDENTITY: The matrix is the identity matrix. + * + * The categories of matrices relevant for GSK and GTK. Note that any + * category includes matrices of all later categories. So if you want + * to for example check if a matrix is a 2D matrix, + * `category >= GSK_MATRIX_CATEGORY_2D` is the way to do this. + * + * Also keep in mind that rounding errors may cause matrices to not + * conform to their categories. Otherwise, matrix operations done via + * mutliplication will not worsen categories. So for the matrix + * multiplication `C = A * B`, `category(C) = MIN (category(A), category(B))`. + */ +typedef enum +{ + GSK_MATRIX_CATEGORY_UNKNOWN, + GSK_MATRIX_CATEGORY_ANY, + GSK_MATRIX_CATEGORY_INVERTIBLE, + GSK_MATRIX_CATEGORY_2D_AFFINE, + GSK_MATRIX_CATEGORY_2D_TRANSLATE, + GSK_MATRIX_CATEGORY_IDENTITY +} GskMatrixCategory; + typedef struct _GskRenderNodeClass GskRenderNodeClass; #define GSK_IS_RENDER_NODE_TYPE(node,type) (GSK_IS_RENDER_NODE (node) && (node)->node_class->node_type == (type)) @@ -58,6 +96,11 @@ GskRenderNode * gsk_render_node_deserialize_node (GskRenderNodeType typ GskRenderNode * gsk_cairo_node_new_for_surface (const graphene_rect_t *bounds, cairo_surface_t *surface); +GskRenderNode * gsk_transform_node_new_with_category (GskRenderNode *child, + const graphene_matrix_t *transform, + GskMatrixCategory category); +GskMatrixCategory gsk_transform_node_get_category (GskRenderNode *node); + GskRenderNode * gsk_text_node_new_with_bounds (PangoFont *font, PangoGlyphString *glyphs, const GdkRGBA *color, diff --git a/gtk/inspector/recorder.c b/gtk/inspector/recorder.c index 26ae9cbdd2..0a56aefb8a 100644 --- a/gtk/inspector/recorder.c +++ b/gtk/inspector/recorder.c @@ -901,6 +901,14 @@ populate_render_node_properties (GtkListStore *store, case GSK_TRANSFORM_NODE: { + static const char * category_names[] = { + [GSK_MATRIX_CATEGORY_UNKNOWN] = "unknown", + [GSK_MATRIX_CATEGORY_ANY] = "any", + [GSK_MATRIX_CATEGORY_INVERTIBLE] = "invertible", + [GSK_MATRIX_CATEGORY_2D_AFFINE] = "2D affine", + [GSK_MATRIX_CATEGORY_2D_TRANSLATE] = "2D transform", + [GSK_MATRIX_CATEGORY_IDENTITY] = "identity" + }; float f[16]; guint i; @@ -913,6 +921,7 @@ populate_render_node_properties (GtkListStore *store, add_text_row (store, i == 0 ? "Matrix" : "", row_string); g_free (row_string); } + add_text_row (store, "Category", category_names[gsk_transform_node_get_category (node)]); } break; -- 2.30.2